package main

// 接口定义 主要约束结构体方法用的 接口名字后面建议加er IF1er 或者自定义类型实现接口 主要结构体实现接口 接口也是一种数据类型
// 1 方法名 参数列表 返回值列表
// type IF1 interface {
// 	add(x, y int) int
// }

// type St struct{}

// func (s St) add(x, y int) int {
// 	return x + y
// }

// 多态
// type Usber interface {
// 	start()
// 	stop()
// }

// type Computer struct{}

// func (c Computer) say(u Usber) {
// 	u.start()
// 	u.stop()
// }

// type Cm struct{}

// func (c Cm) start() {
// 	fmt.Println("c start")
// }
// func (c Cm) stop() {
// 	fmt.Println("c stop")
// }

// 空接口可以被任何值实现 空接口默认值是nil 只声明没有初始化赋值默认nil
// type R interface{}

// 作为函数的参数 可以接受任何值
// func test(x interface{}) {

// }

// type DS struct{}

// 结构体值接收着 结构体指针接收着 接口定义的区别
// 如果是结构体值接收者 实例化后 值类型和指针类型都可以赋值给接口类型
// var 接口类型 = 结构体{} Or &结构体{}  （值类型接收着是啥？就是定义的时候结构体方法前面的(这里是值接收结构体) 方法名字（）{}）
// 如果结构体定义是指针类型接受者 (变量 * 结构体类型) 在赋值给接口类型只能传地址  var 变量 接口类型 = &结构体实例{}
// 接口主要约束结构体的方法 接口定义的方法形式必须和结构体的方法形式除了前面的（变量 结构体类型）固定写法 剩下的完全一样

// 一个结构体实现多个接口
// 定义多个接口类型 里面有多个方法
// 声明多个接口变量
// var aer Aer
// var ber Ber
// aer = St{}
// ber = St{}
// 赋值给多个接口变量
// 其实就是拿接口多个约束 结构体的方法实现

// 接口嵌套
// type Aer interface {
// 	start()
// }
// type Ber interface {
// 	stop()
// }

// type Aller interface {
// 	Aer
// 	Ber
// }

func main() {
	// 1
	// var ssl IF1
	// ssl = St{} // St实现了接口
	// fmt.Println(ssl.add(1, 2)) // 啰嗦一句这里只能调用接口定义的方法即使 实现了多个方法也掉不到接口之外的方法

	// 多态
	// c := Computer{}
	// c.say(Cm{})

	// 空接口被任何值实现
	// var s R
	// s = 1
	// s = 1.0
	// s = "admin"
	// fmt.Println(s)

	// //类型断言
	// d, ok := s.(int) // 返回断言后的值  第二个是否断言成功
	// fmt.Println(d, ok)

	// switch s.(type) { // xx.(type) 只能在switch用
	// case string:
	// 	fmt.Println("string")
	// 	break
	// }

	// var s interface{}
	// s = 1
	// fmt.Println(s)

	// map类型值任意值
	// var a = make(map[string]interface{})
	// a["add"] = 1
	// fmt.Printf("%v", a["add"])

	// 切片的值任意类型 空接口默认值是nil
	// a := make([]interface{}, 4, 4)
	// a[0] = 1
	// a[2] = 1.0
	// fmt.Println(a)

	// 断言 断言主要跟着接口来
	// 变量.(可能的类型) 返回对应的值和是否断言成功 如果变量满足后面的类型就 true

	// 断言可以用于struct 判断被实现的具体类型
	// var as interface{}
	// as = DS{}
	// asd, ok := as.(DS)
	// fmt.Println(asd, ok)

	// 补充空接口 和 类型断言
	// 1
	// as := make(map[string]interface{})
	// as["list"] = make([]string, 4, 4)
	// // as["list"][0] = "admin" // 注意这么玩就直接报错了，需要借助断言
	// // 使用断言
	// if items, ok := as["list"].([]string); ok {
	// 	items[0] = "admins"
	// 	fmt.Println(as)
	// }

	// 这么讲 如果是去实现的空接口 是无法使用.的必须借助断言 如果成功借助断言的返回值来搞 obj,ok := 断言语句  obj.xxx来搞起来

}
